using IQIGame.Extension.Transfer;
using IQIGame.Onigao.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
using UnityEngine.Timeline;

namespace IQIGame.Onigao.GamePlay.Editors
{
    public abstract class GenAnimatorBase
    {
        public const float xOffset = 300f;
        public const float yOffset = 150f;

        public abstract ArtModeGenType genAnimatorType { get; }

        public AnimatorGenConfigAsset genAnimatorConfig { get; protected set; }

        public EntityAnimModifyCollect animResConfig { get; protected set; }

        protected AnimatorController productController { get; set; }

        protected AnimatorStateMachine baseLayerMachine { get; set; }

        public AnimatorControllerLayer[] layers { get; private set; }

        protected string entityName { get; set; }
        public string basePath { get; protected set; }

        private Func<string, ModelImporterClipAnimation, bool> importProcess;
        protected virtual string entityGenConfigPath => $"Assets/EditorConfig/ArtToolConfig/EntityGen/{entityName}.asset";
        protected virtual string defaultGenConfigPath => "Assets/EditorConfig/ArtToolConfig/EntityGen/Common/Entity_LevelEntity.asset";
        protected virtual string animatorConfigPath => $"Assets/EditorConfig/ArtToolConfig/AniamtorGen/Animator_{genAnimatorType.ToString()}.asset";
        public virtual bool GenInitial(string path, string entityName)
        {
            this.basePath = path;
            this.entityName = entityName;
            this.importProcess = this.ProcessModelImporterClipAnimation;
            this.genAnimatorConfig = AssetDatabase.LoadAssetAtPath<AnimatorGenConfigAsset>(animatorConfigPath);
            if (this.genAnimatorConfig == null)
            {
                Debug.LogError("aniamtorGenConfig is null,type:" + genAnimatorType.ToString());
                return false;
            }
            var clipPath = Path.Combine(basePath, this.genAnimatorConfig.AniamtionPath);
            if (!Directory.Exists(clipPath))
            {
                Debug.LogError($"动画目录不存在：{clipPath}");
                return false;
            }

            var genEntityConfig = AssetDatabase.LoadAssetAtPath<EntityGenConfigAsset>(this.entityGenConfigPath);
            if (genEntityConfig == null)
            {
                genEntityConfig = AssetDatabase.LoadAssetAtPath<EntityGenConfigAsset>(this.defaultGenConfigPath);
            }
            if (genEntityConfig != null)
            {
                animResConfig = EntityAnimModifyCollect.Create(genEntityConfig, this.genAnimatorType);
            }

            return true;
        }

        protected void CreateController()
        {
            var animatorResPath = GetAnimatorResPath();
            AnimatorController oldAnimatorController = AssetDatabase.LoadAssetAtPath<AnimatorController>(animatorResPath);
            if (oldAnimatorController != null)
            {
                // 获取特殊组件保留下来
                GetOldAnimatorInfo(oldAnimatorController);
            }
            try
            {
                productController = AnimatorController.CreateAnimatorControllerAtPath(animatorResPath);
            }
            catch (Exception e)
            {
                Debug.LogException(e);
            }
            baseLayerMachine = productController.layers[0].stateMachine;
            baseLayerMachine.entryPosition = Vector3.zero;
            baseLayerMachine.exitPosition = new Vector3(0f, yOffset);
            baseLayerMachine.anyStatePosition = new Vector3(0f, -yOffset);

            CreateOtherLayer();
        }

        public abstract string GetAnimatorResPath();

        protected virtual void GetOldAnimatorInfo(AnimatorController oldAnimatorController)
        {

        }

        protected virtual void CreateOtherLayer()
        {

            for (int i = 0; i < this.genAnimatorConfig.customLayer.Count; i++)
            {
                var layerConfig = this.genAnimatorConfig.customLayer[i];
                productController.AddLayer(layerConfig.layerName);
            }

            layers = productController.layers;
            for (int i = 0; i < this.genAnimatorConfig.customLayer.Count; i++)
            {
                var layerConfig = this.genAnimatorConfig.customLayer[i];
                var animtorLayer = layers[i + 1];
                animtorLayer.defaultWeight = layerConfig.defaultWeight;
                animtorLayer.blendingMode = layerConfig.blendingMode;
                var stateMachine = animtorLayer.stateMachine;
                stateMachine.entryPosition = Vector3.zero;
                stateMachine.exitPosition = new Vector3(0f, yOffset);
                stateMachine.anyStatePosition = new Vector3(0f, -yOffset);
            }

            productController.layers = layers;
        }


        public virtual void AddParameters()
        {
            productController.AddParameter(AnimatorToolConstant.Param_Reset, AnimatorControllerParameterType.Trigger);
            productController.AddParameter(AnimatorToolConstant.Param_Speed, AnimatorControllerParameterType.Float);
            productController.AddParameter(AnimatorToolConstant.Param_JoyStickPower, AnimatorControllerParameterType.Float);
            productController.AddParameter(AnimatorToolConstant.Param_JumpEnd, AnimatorControllerParameterType.Trigger);
            productController.AddParameter(AnimatorToolConstant.Param_Die, AnimatorControllerParameterType.Trigger);
            productController.AddParameter(AnimatorToolConstant.Param_Born, AnimatorControllerParameterType.Trigger);
            productController.AddParameter(AnimatorToolConstant.Param_JumpStart, AnimatorControllerParameterType.Trigger);
            productController.AddParameter(AnimatorToolConstant.Param_Stand2Idle, AnimatorControllerParameterType.Trigger);
            productController.AddParameter(AnimatorToolConstant.Param_StartMove, AnimatorControllerParameterType.Bool);

            for (int i = 0; i < this.genAnimatorConfig.customParam.Count; i++)
            {
                var paramConfig = this.genAnimatorConfig.customParam[i];
                productController.AddParameter(paramConfig.paramName, paramConfig.paramType);
            }
        }


        protected virtual bool ProcessModelImporterClipAnimation(string clipName, ModelImporterClipAnimation modelImporterClip)
        {
            if (this.animResConfig == null || string.IsNullOrEmpty(clipName))
            {
                if (modelImporterClip.events != null && modelImporterClip.events.Length > 0)
                {
                    modelImporterClip.events = null;
                    return true;
                }
                return false;
            }
            if (!this.animResConfig.animResConfigs.TryGetValue(clipName, out var animConfig))
            {
                if (modelImporterClip.events != null && modelImporterClip.events.Length > 0)
                {
                    modelImporterClip.events = null;
                    return true;
                }
                return false;
            }
            var originAnimEvents = modelImporterClip.events;

            // 判断资源上的事件是否和配置一致
            bool eventEqual = true;
            if (originAnimEvents.Length != animConfig.entityAnimEvents.Count)
            {
                eventEqual = false;
            }
            else
            {
                for (int i = 0; i < animConfig.entityAnimEvents.Count; i++)
                {
                    var eventConfig = animConfig.entityAnimEvents[i];
                    var originEvent = originAnimEvents[i];
                    if (eventConfig.time != originEvent.time)
                    {
                        eventEqual = false;
                        break;
                    }
                    if (eventConfig.GetEventFunctionName() != originEvent.functionName)
                    {
                        eventEqual = false;
                        break;
                    }
                    int arg = eventConfig.intArg;
                    if (eventConfig.eventType == EntityAnimEventType.ActiveObject
                        || eventConfig.eventType == EntityAnimEventType.DeactiveObject)
                    {
                        arg += this.animResConfig.effectBindCount;
                    }
                    if (arg != originEvent.intParameter)
                    {
                        eventEqual = false;
                        break;
                    }
                }
            }

            if (eventEqual)
            {
                // 如果一样，就不用修改
                return false;
            }

            List<AnimationEvent> animEventModify = new List<AnimationEvent>();
            for (int i = 0; i < animConfig.entityAnimEvents.Count; i++)
            {
                // 创建AnimationEvents
                var eventConfig = animConfig.entityAnimEvents[i];
                var originEvent = new AnimationEvent();
                originEvent.time = eventConfig.time;
                originEvent.functionName = eventConfig.GetEventFunctionName();
                int arg = eventConfig.intArg;
                if (eventConfig.eventType == EntityAnimEventType.ActiveObject
                    || eventConfig.eventType == EntityAnimEventType.DeactiveObject)
                {
                    arg += this.animResConfig.effectBindCount;
                }
                originEvent.intParameter = arg;
                animEventModify.Add(originEvent);
            }
            modelImporterClip.events = animEventModify.ToArray();

            return true;
        }

        public virtual string GetAnimationClipPath(string clipName)
        {
            var clipPath = Path.Combine(basePath, this.genAnimatorConfig.AniamtionPath, $"{entityName}@{clipName}.FBX").Replace("\\", "/");
            var guid = AssetDatabase.AssetPathToGUID(clipPath);
            #region 检查大小写
            //由于windows系统下加载不区分大小写，会导致当clipName配置名和资源名大小写不匹配时，生成工具依然有效。
            //但其他配置对应clipName时，只能对应到配置名，而无法对应到资源名（如果对应资源名会有很多低效代码）
            //这种不匹配会导致策划容易困惑到底标准是什么（例如特效对应的动画名和实际资源名不一致）。
            //可以认为这是由于windows系统加载的“兼容”，导致代码原本要求严格对应超出了预期，算是一个bug，虽然它不影响运行，但影响标准化管理。
            //所以干脆这里强制要求大小写必须匹配。
            if (!string.IsNullOrEmpty(guid))
            {
                var filePath = AssetDatabase.GUIDToAssetPath(guid);
                var fileName = Path.GetFileNameWithoutExtension(filePath);
                var resClipName = fileName.Substring(fileName.IndexOf('@') + 1);
                if (clipName != resClipName)
                {
                    Debug.LogError($"实体[{entityName}]配置的动画名大小写与动画资源命名不匹配。配置名称：{clipName}，资源名称：{Path.GetFileName(filePath)}");
                }
                if (Path.GetExtension(filePath) != ".FBX")
                {
                    Debug.LogError($"资源 {Path.GetFileName(filePath)} 后缀名不是大写");
                }
            }
            #endregion 检查大小写
            return clipPath;
        }

        public virtual AnimationClip GetAniamtionClip(string clipName)
        {
            var clipPath = GetAnimationClipPath(clipName);
            var clip = AnimatorFactoryUtil.LoadAnimClip(clipPath);
            return clip;
        }

        public virtual AnimationClip GetAnimationClipAndSetLoop(string clipName, bool isLoop)
        {
            var clipPath = GetAnimationClipPath(clipName);
            var clip = AnimatorFactoryUtil.LoadAnimClipAndSetLoopExtend(clipPath, clipName, entityName, isLoop, this.importProcess);
            return clip;
        }

        public virtual AnimationClip GetAnimationClipByPath(string clipPath, bool isLoop)
        {
            var clipFileName = Path.GetFileNameWithoutExtension(clipPath);
            var fileNameArray = clipFileName.Split('@');
            string clipName = string.Empty;
            if (fileNameArray.Length == 2)
            {
                clipName = fileNameArray[1];
            }
            var clip = AnimatorFactoryUtil.LoadAnimClipAndSetLoopExtend(clipPath, clipName, entityName, isLoop, this.importProcess);
            return clip;
        }

        /// <summary>
        /// 根据AnimationClip的clip name等关键参数创建AnimatorState
        /// clip name: 如Idle
        /// </summary>
        /// <param name="layerMachine"></param>
        /// <param name="stateName"></param>
        /// <param name="clipName"></param>
        /// <param name="isLoop"></param>
        /// <param name="pos"></param>
        /// <param name="animatorState"></param>
        /// <returns>创建是否成功，如果失败则该状态可忽略</returns>
        protected bool CreateAnimatorState(AnimatorStateMachine layerMachine, string stateName, string clipName, bool isLoop, Vector3 pos, out AnimatorState animatorState)
        {
            var animClip = this.GetAnimationClipAndSetLoop(clipName, isLoop);
            if (animClip == null)
            {
                animatorState = null;
                return false;
            }
            animatorState = InnerCreateAnimatorState(layerMachine, stateName, animClip, pos);
            return true;
        }

        /// <summary>
        /// 根据AnimationClip的file path等关键参数创建AnimatorState
        /// file path: 如Assets/Res/04_ArtModel/Character/WeiYang_bird/Animation\WeiYang_bird@Attack.FBX
        /// </summary>
        /// <param name="layerMachine"></param>
        /// <param name="stateName"></param>
        /// <param name="clipName"></param>
        /// <param name="isLoop"></param>
        /// <param name="pos"></param>
        /// <param name="animatorState"></param>
        /// <returns>创建是否成功，如果失败则该状态可忽略</returns>
        protected bool CreateAnimatorStateByPath(AnimatorStateMachine layerMachine, string stateName, string clipFilePath, bool isLoop, Vector3 pos, out AnimatorState animatorState)
        {
            var animClip = this.GetAnimationClipByPath(clipFilePath, isLoop);
            if (animClip == null)
            {
                animatorState = null;
                return false;
            }
            animatorState = InnerCreateAnimatorState(layerMachine, stateName, animClip, pos);
            return true;
        }

        protected AnimatorState InnerCreateAnimatorState(AnimatorStateMachine layerMachine, string stateName, AnimationClip animClip, Vector3 pos)
        {
            var animatorState = layerMachine.AddState(stateName, pos);
            animatorState.motion = animClip;
            return animatorState;
        }

        private bool IsGroupInTimeline(string groupName, string timelinePath)
        {
            TimelineAsset timeline = AssetDatabase.LoadAssetAtPath<TimelineAsset>(timelinePath);
            if (timeline == null)
            {
                return false;
            }
            Dictionary<string, TrackAsset> timelineGroups = null;
            DataTransferUtility.GetTimelineGroups(timeline, ref timelineGroups);
            foreach (var key in timelineGroups.Keys)
            {
                if (key == groupName)
                {
                    return true;
                }
            }
            return false;
        }

        protected void AddResetToDefaultState(AnimatorStateMachine layerMachine)
        {
            var trans = layerMachine.AddAnyStateTransition(layerMachine.defaultState);
            trans.hasExitTime = false;
            trans.duration = GenAnimatorTimeConst.TransDuration_ToDefault;
            trans.interruptionSource = TransitionInterruptionSource.Destination;
            trans.AddCondition(AnimatorConditionMode.If, 0, AnimatorToolConstant.Param_Reset);
        }


        /// <summary>
        /// 创建基础的初始状态
        /// </summary>
        /// <param name="layerMachine"></param>
        /// <param name="isDefault"></param>
        /// <param name="pos"></param>
        public virtual AnimatorState CreateBaseIdleState(AnimatorStateMachine layerMachine, bool isDefault, Vector3 pos)
        {
            AnimatorState stateStand = null;
            var idleClip = this.GetAnimationClipAndSetLoop(this.genAnimatorConfig.Name_Idle, true);
            var walkClip = this.GetAnimationClipAndSetLoop(this.genAnimatorConfig.Name_Walk, true);
            if (idleClip != null && walkClip != null)
            {
                var runClip = this.GetAnimationClipAndSetLoop(this.genAnimatorConfig.Name_Run, true);

                BlendTree battleStandTree = new BlendTree();
                battleStandTree.name = AnimatorToolConstant.State_IdleMoveTree;
                battleStandTree.blendType = BlendTreeType.Simple1D;
                battleStandTree.useAutomaticThresholds = false;
                battleStandTree.blendParameter = AnimatorToolConstant.Param_Speed;

                battleStandTree.AddChild(idleClip, GenAnimatorTimeConst.BlendTreeIdleStart);
                //battleStandTree.AddChild(walkClip, GenAnimatorTimeConst.BlendTreeSlowWalkStart);
                battleStandTree.AddChild(walkClip, GenAnimatorTimeConst.BlendTreeWalkStart);
                battleStandTree.AddChild(runClip, GenAnimatorTimeConst.BlendTreeRunStart);

                var children = battleStandTree.children;
                children[0].timeScale = GenAnimatorTimeConst.BlendTreeNormalRatio;
                children[1].timeScale = GenAnimatorTimeConst.BlendTreeNormalRatio;
                //children[1].timeScale = GenAnimatorTimeConst.BlendTreeSlowWalkRatio;
                children[2].timeScale = GenAnimatorTimeConst.BlendTreeNormalRatio;
                //children[3].timeScale = GenAnimatorTimeConst.BlendTreeNormalRatio;
                battleStandTree.children = children;

                if (AssetDatabase.GetAssetPath(productController) != string.Empty)
                {
                    AssetDatabase.AddObjectToAsset(battleStandTree, AssetDatabase.GetAssetPath(productController));
                }

                stateStand = layerMachine.AddState(AnimatorToolConstant.State_IdleMoveTree, pos);
                stateStand.motion = battleStandTree;

            }
            else if (idleClip != null)
            {

                stateStand = layerMachine.AddState(AnimatorToolConstant.State_Idle, pos);
                stateStand.motion = idleClip;
            }
            else
            {
                stateStand = layerMachine.AddState(AnimatorToolConstant.State_Empty, pos);
            }
            if (isDefault)
            {
                layerMachine.defaultState = stateStand;
            }
            return stateStand;
        }


        /// <summary>
        /// 创建长期不动的休闲状态
        /// </summary>
        /// <param name="layerMachine"></param>
        /// <param name="pos"></param>
        /// <param name="nextState"></param>
        /// <returns></returns>
        public virtual bool CreateLongIdleState(AnimatorStateMachine layerMachine, Vector3 pos, AnimatorState nextState = null)
        {
            if (!CreateAnimatorState(layerMachine, AnimatorToolConstant.State_LongIdle,
                this.genAnimatorConfig.Name_LongIdle, false,
                pos, out var stateLongIdle))
            {
                return false;
            }

            if (nextState != null)
            {
                // 自动切换动作Behaviour
                var autoSwitch = nextState.AddStateMachineBehaviour<AnimAutoSwtichTrigger>();
                autoSwitch.autoSwitch = true;
                autoSwitch.autoTriggerName = AnimatorToolConstant.Param_Stand2Idle;
                autoSwitch.autoSwitchInterval = this.genAnimatorConfig.LongIdleInterval;
                autoSwitch.resetType = AnimSwitchResetType.SpeedGreatZero;
                autoSwitch.resetParameterName = AnimatorToolConstant.Param_Speed;

                // 动画状态转换
                var trans = nextState.AddTransition(stateLongIdle);
                trans.hasExitTime = false;
                trans.duration = GenAnimatorTimeConst.TransDuration_ToLongIdle;
                trans.interruptionSource = TransitionInterruptionSource.Destination;
                trans.AddCondition(AnimatorConditionMode.If, 0, AnimatorToolConstant.Param_Stand2Idle);


                trans = stateLongIdle.AddTransition(nextState, true);
                trans.hasExitTime = true;
                trans.duration = GenAnimatorTimeConst.TransDuration_LongIdleToDefault_TimesUp;
                trans.interruptionSource = TransitionInterruptionSource.Destination;

                trans = stateLongIdle.AddTransition(nextState, true);
                trans.hasExitTime = false;
                trans.duration = GenAnimatorTimeConst.TransDuration_LongIdleToDefault_Move;
                trans.interruptionSource = TransitionInterruptionSource.Destination;
                trans.AddCondition(AnimatorConditionMode.Greater, 1e-3f, AnimatorToolConstant.Param_Speed);

            }
            return true;
        }

        /// <summary>
        /// 创建基础的转向状态
        /// </summary>
        /// <param name="layerMachine"></param>
        /// <param name="pos"></param>
        public virtual bool CreateTurnState(AnimatorStateMachine layerMachine, Vector3 pos, AnimatorState nextState = null)
        {
            const float yOffsetInterval = 80;
            const float xOffsetInterval = 20;
            pos.x -= xOffsetInterval;
            if (!CreateAnimatorState(layerMachine, AnimatorToolConstant.State_TurnLeft,
                this.genAnimatorConfig.Name_TurnLeft, false,
                pos, out var stateTurnLeft))
            {
                return false;
            }

            pos.y += yOffsetInterval;
            pos.x += xOffsetInterval * 2;
            if (!CreateAnimatorState(layerMachine, AnimatorToolConstant.State_TurnRight,
                this.genAnimatorConfig.Name_TurnRight, false,
                pos, out var stateTurnRight))
            {
                return false;
            }

            if (nextState != null)
            {
                var trans = stateTurnLeft.AddTransition(nextState, true);
                trans.hasExitTime = true;
                trans.interruptionSource = TransitionInterruptionSource.Destination;

                trans = stateTurnRight.AddTransition(nextState, true);
                trans.hasExitTime = true;
                trans.interruptionSource = TransitionInterruptionSource.Destination;
            }
            return true;
        }

        /// <summary>
        /// 创建基础的死亡状态
        /// </summary>
        /// <param name="layerMachine"></param>
        /// <param name="pos"></param>
        public virtual bool CreateDieState(AnimatorStateMachine layerMachine, Vector3 pos)
        {
            if (!CreateAnimatorState(layerMachine, AnimatorToolConstant.State_Die,
                this.genAnimatorConfig.Name_Die, false,
                pos, out var stateDie))
            {
                return false;
            }
            // 添加触发
            var trans = layerMachine.AddAnyStateTransition(stateDie);
            trans.hasExitTime = false;
            trans.duration = GenAnimatorTimeConst.TransDuration_ToDie;
            trans.interruptionSource = TransitionInterruptionSource.Destination;
            trans.AddCondition(AnimatorConditionMode.If, 0, AnimatorToolConstant.Param_Die);

            return true;
        }

        /// <summary>
        /// 创建基础的出生状态
        /// </summary>
        /// <param name="layerMachine"></param>
        /// <param name="pos"></param>
        /// <param name="nextState"></param>
        /// <returns></returns>
        public virtual bool CreateBornState(AnimatorStateMachine layerMachine, Vector3 pos, AnimatorState nextState = null)
        {
            if (!CreateAnimatorState(layerMachine, AnimatorToolConstant.State_Born,
                this.genAnimatorConfig.Name_Born, false,
                pos, out var stateBorn))
            {
                return false;
            }
            var trans = layerMachine.AddAnyStateTransition(stateBorn);
            trans.hasExitTime = false;
            trans.duration = GenAnimatorTimeConst.TransDuration_ToBorn;
            trans.interruptionSource = TransitionInterruptionSource.Destination;
            trans.AddCondition(AnimatorConditionMode.If, 0, AnimatorToolConstant.Param_Born);

            if (nextState != null)
            {
                trans = stateBorn.AddTransition(nextState, true);
                trans.hasExitTime = true;
                trans.interruptionSource = TransitionInterruptionSource.Destination;
            }
            return true;
        }

        /// <summary>
        /// 创建基础的跳跃状态
        /// </summary>
        /// <param name="layerMachine"></param>
        /// <param name="startPos"></param>
        /// <param name="nextState"></param>
        /// <returns></returns>
        public virtual bool CreateJumpState(AnimatorStateMachine layerMachine, Vector3 startPos, AnimatorState nextState = null)
        {
            if (!CreateAnimatorState(layerMachine, AnimatorToolConstant.State_JumpStart,
                this.genAnimatorConfig.Name_JumpStart, false,
                startPos, out var stateJumpStart))
            {
                return false;
            }
            if (!CreateAnimatorState(layerMachine, AnimatorToolConstant.State_JumpLoop,
                this.genAnimatorConfig.Name_JumpLoop, true,
                new Vector3(startPos.x, startPos.y + yOffset), out var stateJumpLoop))
            {
                return false;
            }
            if (!CreateAnimatorState(layerMachine, AnimatorToolConstant.State_JumpEnd,
                this.genAnimatorConfig.Name_JumpEnd, false,
                new Vector3(startPos.x, startPos.y + yOffset * 2), out var stateJumpEnd))
            {
                return false;
            }

            var trans = stateJumpStart.AddTransition(stateJumpLoop, true);
            trans.hasExitTime = true;
            trans.interruptionSource = TransitionInterruptionSource.DestinationThenSource;
            trans.duration = this.genAnimatorConfig.Time_JumpStartToLoop;

            trans = stateJumpLoop.AddTransition(stateJumpEnd, true);
            trans.hasExitTime = false;
            trans.duration = this.genAnimatorConfig.Time_JumpLoopToEnd;
            trans.AddCondition(AnimatorConditionMode.If, 0, AnimatorToolConstant.Param_JumpEnd);

            trans = layerMachine.AddAnyStateTransition(stateJumpStart);
            trans.hasExitTime = false;
            trans.duration = this.genAnimatorConfig.Time_JumpStartSiwtch;
            trans.AddCondition(AnimatorConditionMode.If, 0, AnimatorToolConstant.Param_JumpStart);

            if (nextState != null)
            {
                trans = stateJumpEnd.AddTransition(nextState, true);
                trans.hasExitTime = true;
                trans.interruptionSource = TransitionInterruptionSource.DestinationThenSource;
            }

            return true;
        }

        /// <summary>
        /// 创建动态动作
        /// </summary>
        /// <param name="prefix"></param>
        /// <param name="layerMachine"></param>
        /// <param name="xOffset"></param>
        /// <param name="nextState"></param>
        public void CreateCreateDynState(AnimatorGenConfigAsset.AniamtorCustomeActionPrefix prefixConfig, AnimatorStateMachine layerMachine, ref Vector3 startPos,
            AnimatorState nextState = null, Action<AnimatorState> customProcess = null)
        {
            var prefix = prefixConfig.prefix;
            var isReplacePrefix = prefixConfig.isReplacePrefix;
            var repleacePrefix = prefixConfig.replacePrefix;
            //加载目录下所有prefix开头的动态动画
            var clipPath = Path.Combine(basePath, this.genAnimatorConfig.AniamtionPath).Replace("\\", "/");
            if (!Directory.Exists(clipPath))
            {
                Debug.LogError($"动画目录不存在：{clipPath}");
                return;
            }

            var clipName = $"{entityName}@{prefix}";
            var rFileName = clipName + "*.FBX";
            var skillFbxFiles = Directory.GetFiles(clipPath, rFileName, SearchOption.TopDirectoryOnly);
            string skillNamePatten = $"@({prefix}" + @"[^\\\/]*)\.FBX$";
            Regex rex = new Regex(skillNamePatten, RegexOptions.IgnoreCase);
            const float yOffsetInterval = 80;
            List<AnimatorState> skillStateList = new List<AnimatorState>();
            Dictionary<string, AnimatorState> loopSkillStartDic = new Dictionary<string, AnimatorState>(); //start -> loop 的循环的技能
            foreach (var fileName in skillFbxFiles)
            {
                var match = rex.Match(fileName);
                if (string.IsNullOrEmpty(match.Value) || match.Groups.Count < 2)
                {
                    continue;
                }
                // 这里根据文件名拆出了动作名，无法在同一文件中指定多个动作导出
                var stateName = match.Groups[1].Value;

                bool isLoop = false;
                AnimatorGenConfigAsset.AniamtorCustomeActionLoop loopConfig = null;
                //是loop动画
                for (int i = 0; i < this.genAnimatorConfig.customeActionLoops.Count; i++)
                {
                    loopConfig = this.genAnimatorConfig.customeActionLoops[i];
                    if (stateName.EndsWith(loopConfig.loopSuffixName))
                    {
                        isLoop = true;
                        break;
                    }
                }

                startPos.y += yOffsetInterval;
                var showStateName = stateName;
                if (isReplacePrefix)
                {
                    showStateName = repleacePrefix + showStateName.Substring(prefix.Length);
                }

                if (!CreateAnimatorStateByPath(layerMachine, showStateName,
                    fileName, isLoop,
                    startPos, out var stateSkill))
                {
                    continue;
                }

                skillStateList.Add(stateSkill);

                if (isLoop && loopConfig.hasStartToLoop)
                {
                    if (!stateSkill.motion.isLooping)
                    {
                        LogGame.LogError($"{stateSkill.name}名称为循环动画但是资源不循环");
                    }
                    loopSkillStartDic.Add(stateName.Replace(loopConfig.loopSuffixName, loopConfig.startRepleceSuffixName), stateSkill);
                }

            }

            //非循环的状态才加自动转换功能
            foreach (var stateSkill in skillStateList)
            {
                if (loopSkillStartDic.TryGetValue(stateSkill.name, out var skillLoopState))
                {
                    var trans = stateSkill.AddTransition(skillLoopState, true);
                    trans.hasExitTime = true;
                    SetDefaultTransitionExitTime(stateSkill, trans);
                    trans.interruptionSource = TransitionInterruptionSource.Destination;
                }
                else if (!stateSkill.motion.isLooping)
                {
                    var trans = stateSkill.AddTransition(nextState, true);
                    trans.hasExitTime = true;
                    SetDefaultTransitionExitTime(stateSkill, trans);
                    trans.interruptionSource = TransitionInterruptionSource.Destination;
                }
                // else if (stateSkill.motion.isLooping && !string.IsNullOrEmpty(prefixConfig.loopParamName) && nextState != null)
                // {
                //     var trans = stateSkill.AddTransition(nextState, false);
                //     trans.AddCondition(AnimatorConditionMode.IfNot, 0, prefixConfig.loopParamName);
                //     var trans2 = nextState.AddTransition(stateSkill, false);
                //     trans2.AddCondition(AnimatorConditionMode.If, 0, prefixConfig.loopParamName);
                //     
                //     trans.interruptionSource = TransitionInterruptionSource.Destination;
                //     trans2.interruptionSource = TransitionInterruptionSource.Destination;
                // }
            }

            if (customProcess != null)
            {
                foreach (var stateSkill in skillStateList)
                {
                    customProcess.Invoke(stateSkill);
                }
            }

        }

        private void SetDefaultTransitionExitTime(AnimatorState state, AnimatorStateTransition trans)
        {
            if (state.motion != null && state.motion.averageDuration >= 0f)
            {
                var duration = state.motion.averageDuration;
                var tansTime = GenAnimatorTimeConst.DefaultTransDuration;
                #region 保底规则，不管默认过度时间怎么变，这个保底规则都可以不变
                if (duration < 0.2f && tansTime > 0)
                {
                    tansTime = 0f;
                }
                else if (duration < 0.45f && tansTime > 0.1f)
                {
                    tansTime = 0.1f;
                }
                #endregion 保底规则
                float num = tansTime / duration;
                trans.duration = tansTime;
                trans.exitTime = 1f - num;
            }
        }

        /// <summary>
        /// 创建额外自定义的动作
        /// </summary>
        protected virtual void CreateCustomAction(AnimatorStateMachine layerMachine, int layerIndex, float startXOffset, AnimatorState nextState = null)
        {
            Vector3 startPos = new Vector3(startXOffset, -3 * yOffset);
            for (int i = 0; i < this.genAnimatorConfig.customPrefix.Count; i++)
            {
                var prefixConfig = this.genAnimatorConfig.customPrefix[i];
                if (prefixConfig.layer != layerIndex)
                {
                    continue;
                }
                this.CreateCreateDynState(prefixConfig, layerMachine, ref startPos, nextState, (customState) =>
                    {
                        // 添加参数
                        for (int j = 0; j < prefixConfig.transitions.Count; j++)
                        {
                            var transitionConfig = prefixConfig.transitions[j];

                            var tranState = string.IsNullOrEmpty(transitionConfig.targetName) ? nextState : layerMachine.GetStateByName(transitionConfig.targetName);
                            if (tranState != null)
                            {
                                if (customState.motion.isLooping && (transitionConfig.addType & AnimatorGenConfigAsset.EAniamtorCustomTransitionAddType.Loop) <= 0)
                                {
                                    continue;
                                }
                                if (!customState.motion.isLooping && (transitionConfig.addType & AnimatorGenConfigAsset.EAniamtorCustomTransitionAddType.NotLoop) <= 0)
                                {
                                    continue;
                                }
                                AnimatorStateTransition trans;
                                if (transitionConfig.back)
                                {
                                    trans = tranState.AddTransition(customState, true);
                                }
                                else
                                {
                                    trans = customState.AddTransition(tranState, true);
                                }
                                trans.hasExitTime = false;
                                trans.duration = transitionConfig.duration;
                                trans.interruptionSource = TransitionInterruptionSource.DestinationThenSource;
                                trans.AddCondition(transitionConfig.paramMode, transitionConfig.paramValue, transitionConfig.paramName);
                            }
                        }
                    });
            }
        }

        protected virtual void CreateCustomLayerState()
        {
            for (int i = 0; i < this.genAnimatorConfig.customLayer.Count; i++)
            {
                var layerConfig = this.genAnimatorConfig.customLayer[i];
                var animtorLayer = layers[i + 1];
                var stateMachine = animtorLayer.stateMachine;
                // 创建基础状态
                var stateEmpty = stateMachine.AddState(AnimatorToolConstant.State_Empty, new Vector3(xOffset, 0));
                stateMachine.defaultState = stateEmpty;
                AddResetToDefaultState(stateMachine);

                // 创建死亡状态(如果有的情况下)
                _ = CreateDieState(stateMachine, new Vector3(xOffset, -yOffset));

                CreateCustomAction(stateMachine, i + 1, xOffset * 2, stateMachine.defaultState);

                AddStateBehaviour(stateMachine);
            }

        }

        /// <summary>
        /// 给状态添加脚本
        /// </summary>
        public void AddStateBehaviour(AnimatorStateMachine stateMachine)
        {
            if (this.animResConfig == null)
            {
                return;
            }
            foreach (ChildAnimatorState childState in stateMachine.states)
            {
                var animatorState = childState.state;
                if (this.animResConfig.stateGoAcitveReset.TryGetValue(animatorState.name, out var activeReset))
                {
                    var stateBehaviour = animatorState.AddStateMachineBehaviour<AnimatorGoActiveReset>();
                    var stateBind = activeReset.stateBindInfo;
                    stateBehaviour.isShowByParam = stateBind.triggerType == TriggerType.ShowByParam;
                    if (stateBehaviour.isShowByParam)
                    {
                        stateBehaviour.comparisonType = stateBind.animatorParamComparisonType;
                        stateBehaviour.paramId = GetParamId(stateBind.animatorParamType);
                        stateBehaviour.targetValue = stateBind.animatorParamValue;
                        stateBehaviour.showOnMeetCondition = stateBind.showOnMeetCondition;
                    }
                    stateBehaviour.hideObjectIndex = activeReset.objIndexs.ToArray();
                }
                if (this.animResConfig.vfxConfigs.TryGetValue(animatorState.name, out var vfxConfig))
                {
                    AnimatorVFXPlayer vfxPlayer = animatorState.AddStateMachineBehaviour<AnimatorVFXPlayer>();
                    //先检查专用timeline
                    if (IsGroupInTimeline(vfxConfig.vfxGroup, $"Assets/{Game.PathConstant.commonVFXAssetPath}"))
                    {
                        vfxPlayer.configGroup = vfxConfig.vfxGroup;
                        vfxPlayer.configDelay = vfxConfig.delay;
                    }
                    else if (IsGroupInTimeline(vfxConfig.vfxGroup, $"Assets/{Game.PathConstant.GetEntityVFXAssetPath(entityName)}"))
                    {
                        vfxPlayer.configGroup = vfxConfig.vfxGroup;
                        vfxPlayer.configDelay = vfxConfig.delay;
                    }
                    else
                    {
                        Debug.LogError($"{entityName} 根据VFX配置找不到对应的VFX group。state: {vfxConfig.stateName}, group: {vfxConfig.vfxGroup}");
                    }
                }
            }
        }

        private int GetParamId(StateParamType paramType)
        {
            switch (paramType)
            {
                case StateParamType.Speed: return AnimationConst.Param_Speed;
            }
            Debug.LogError($"不支持的类型：{paramType}");
            return 0;
        }

        public abstract void GenAnimatorController();

    }
}
